package com.czk.plugins.practice;

import com.czk.anotation.IdReplace;
import com.czk.desensitization.practice.IdReplaceStrategy;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.sql.Statement;
import java.util.List;
import java.util.stream.Stream;

/**
 * id替换策略
 *
 * @Author:ChenZhangKun
 * @Date: 2021/7/22 10:55
 */
@Component
@Intercepts(@Signature(
        type = ResultSetHandler.class, method = "handleResultSets", args = Statement.class
))
public class IdReplacePlugin implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 执行任务
        List<Object> proceed = (List<Object>) invocation.proceed();
        // 遍历
        proceed.forEach(this::idReplace);
        return proceed;
    }

    private void idReplace(Object obj) {
        // 拿到元数据
        MetaObject metaObject = SystemMetaObject.forObject(obj);
        // 拿到字节码对象
        Class<?> clazz = obj.getClass();
        // 遍历
        Stream.of(clazz.getDeclaredFields()).filter(x -> x.isAnnotationPresent(IdReplace.class)).forEach(x -> {
            doReplace(x, metaObject);
        });
    }

    /**
     * 执行id替换
     *
     * @param filed      字段
     * @param metaObject 该对象的元数据
     */
    private void doReplace(Field filed, MetaObject metaObject) {
        // 拿到子弹名称
        String name = filed.getName();
        // 拿到字段对应的值
        Object value = metaObject.getValue(name);
        // 判断
        // 是否是Integer类型
        if (Integer.class == metaObject.getGetterType(name) && value != null) {
            // 拿到注解
            IdReplace annotation = filed.getAnnotation(IdReplace.class);
            // 拿到策略
            IdReplaceStrategy strategy = annotation.strategy();
            // 执行策略
            Integer integer = strategy.getIdReplace().apply((Integer) value);
            // 重置结果
            metaObject.setValue(name, integer);
        }
    }
}
